using Lzfy_Refund_Service.Models;
using System.Security.Cryptography;
using System.Text;
using System.Xml.Linq;
using Microsoft.Extensions.Options;

namespace Lzfy_Refund_Service.Services
{
    /// <summary>
    /// 微信推送通知服务实现
    /// </summary>
    public class WeChatNotificationService : IWeChatNotificationService
    {
        private readonly IHisPatientBalanceService _hisPatientBalanceService;
        private readonly ILogger<WeChatNotificationService> _logger;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly WeChatConfiguration _weChatConfig;

        public WeChatNotificationService(
            IHisPatientBalanceService hisPatientBalanceService,
            ILogger<WeChatNotificationService> logger,
            IHttpClientFactory httpClientFactory,
            IOptions<WeChatConfiguration> weChatConfig)
        {
            _hisPatientBalanceService = hisPatientBalanceService;
            _logger = logger;
            _httpClientFactory = httpClientFactory;
            _weChatConfig = weChatConfig.Value;
        }

        /// <summary>
        /// 发送退费申请提交成功通知
        /// </summary>
        public async Task<WeChatNotificationResult> SendRefundSubmittedNotificationAsync(string patientId, int refundId)
        {
            try
            {
                if (!_weChatConfig.Enabled)
                {
                    _logger.LogInformation("微信推送功能已禁用");
                    return new WeChatNotificationResult
                    {
                        Success = true,
                        Message = "微信推送功能已禁用，跳过发送"
                    };
                }

                var currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                var qrCode = await _hisPatientBalanceService.GetPatientQrCodeAsync(patientId);

                if (string.IsNullOrEmpty(qrCode))
                {
                    return new WeChatNotificationResult
                    {
                        Success = false,
                        Message = "无法获取患者qrCode",
                        ErrorDetails = $"患者ID: {patientId}"
                    };
                }

                // 处理qrCode格式，去掉前缀和后缀
                var processedQrCode = ProcessQrCode(qrCode);

                var request = new WeChatMessageRequest
                {
                    ServiceCode = _weChatConfig.ServiceCode,
                    PartnerId = _weChatConfig.PartnerId,
                    TimeStamp = currentTime,
                    CardNo = processedQrCode,
                    MsgType = WeChatMessageTemplates.RefundSubmitted.MsgType.ToString(),
                    MsgContext = currentTime,
                    PersonalFirst = WeChatMessageTemplates.RefundSubmitted.PersonalFirst,
                    PersonalSecond = WeChatMessageTemplates.RefundSubmitted.PersonalSecond,
                    Channel = _weChatConfig.Channel
                };

                return await SendWeChatNotificationAsync(request, $"退费申请提交成功通知 - 患者ID: {patientId}, 退费ID: {refundId}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"发送退费申请提交成功通知失败 - 患者ID: {patientId}, 退费ID: {refundId}");
                return new WeChatNotificationResult
                {
                    Success = false,
                    Message = "发送通知失败",
                    ErrorDetails = ex.Message
                };
            }
        }

        /// <summary>
        /// 发送退费审核通过通知
        /// </summary>
        public async Task<WeChatNotificationResult> SendRefundApprovedNotificationAsync(string patientId, int refundId)
        {
            try
            {
                if (!_weChatConfig.Enabled)
                {
                    _logger.LogInformation("微信推送功能已禁用");
                    return new WeChatNotificationResult
                    {
                        Success = true,
                        Message = "微信推送功能已禁用，跳过发送"
                    };
                }

                var currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                var qrCode = await _hisPatientBalanceService.GetPatientQrCodeAsync(patientId);

                if (string.IsNullOrEmpty(qrCode))
                {
                    return new WeChatNotificationResult
                    {
                        Success = false,
                        Message = "无法获取患者qrCode",
                        ErrorDetails = $"患者ID: {patientId}"
                    };
                }
                
                // 处理qrCode格式，去掉前缀和后缀
                var processedQrCode = ProcessQrCode(qrCode);
                
                var request = new WeChatMessageRequest
                {
                    ServiceCode = _weChatConfig.ServiceCode,
                    PartnerId = _weChatConfig.PartnerId,
                    TimeStamp = currentTime,
                    CardNo = processedQrCode,
                    MsgType = WeChatMessageTemplates.RefundApproved.MsgType.ToString(),
                    MsgContext = currentTime,
                    PersonalFirst = WeChatMessageTemplates.RefundApproved.PersonalFirst,
                    PersonalSecond = WeChatMessageTemplates.RefundApproved.PersonalSecond,
                    Channel = _weChatConfig.Channel
                };

                return await SendWeChatNotificationAsync(request, $"退费审核通过通知 - 患者ID: {patientId}, 退费ID: {refundId}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"发送退费审核通过通知失败 - 患者ID: {patientId}, 退费ID: {refundId}");
                return new WeChatNotificationResult
                {
                    Success = false,
                    Message = "发送通知失败",
                    ErrorDetails = ex.Message
                };
            }
        }

        /// <summary>
        /// 发送退费审核拒绝通知
        /// </summary>
        public async Task<WeChatNotificationResult> SendRefundRejectedNotificationAsync(string patientId, int refundId, string reason)
        {
            try
            {
                if (!_weChatConfig.Enabled)
                {
                    _logger.LogInformation("微信推送功能已禁用");
                    return new WeChatNotificationResult
                    {
                        Success = true,
                        Message = "微信推送功能已禁用，跳过发送"
                    };
                }

                var currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                var qrCode = await _hisPatientBalanceService.GetPatientQrCodeAsync(patientId);

                if (string.IsNullOrEmpty(qrCode))
                {
                    return new WeChatNotificationResult
                    {
                        Success = false,
                        Message = "无法获取患者qrCode",
                        ErrorDetails = $"患者ID: {patientId}"
                    };
                }
                
                // 处理qrCode格式，去掉前缀和后缀
                var processedQrCode = ProcessQrCode(qrCode);
                
                var request = new WeChatMessageRequest
                {
                    ServiceCode = _weChatConfig.ServiceCode,
                    PartnerId = _weChatConfig.PartnerId,
                    TimeStamp = currentTime,
                    CardNo = processedQrCode,
                    MsgType = WeChatMessageTemplates.RefundRejected.MsgType.ToString(),
                    MsgContext = currentTime,
                    PersonalFirst = WeChatMessageTemplates.RefundRejected.PersonalFirst,
                    PersonalSecond = WeChatMessageTemplates.RefundRejected.PersonalSecond,//string.IsNullOrWhiteSpace(reason) ? "如有疑问请联系客服" : reason,
                    Channel = _weChatConfig.Channel
                };

                return await SendWeChatNotificationAsync(request, $"退费审核拒绝通知 - 患者ID: {patientId}, 退费ID: {refundId}, 拒绝原因: {reason}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"发送退费审核拒绝通知失败 - 患者ID: {patientId}, 退费ID: {refundId}");
                return new WeChatNotificationResult
                {
                    Success = false,
                    Message = "发送通知失败",
                    ErrorDetails = ex.Message
                };
            }
        }

        /// <summary>
        /// 发送微信通知的通用方法
        /// </summary>
        private async Task<WeChatNotificationResult> SendWeChatNotificationAsync(WeChatMessageRequest request, string logMessage)
        {
            var requestId = Guid.NewGuid().ToString("N")[..8]; // 生成8位请求ID用于日志追踪
            
            try
            {
                _logger.LogInformation($"[{requestId}] {logMessage} - 开始处理");
                
                // 记录配置信息
                _logger.LogInformation($"[{requestId}] 微信推送配置: {{@Config}}", new {
                    _weChatConfig.Enabled,
                    _weChatConfig.ServiceCode,
                    _weChatConfig.PartnerId,
                    _weChatConfig.Channel,
                    ApiUrl = string.IsNullOrWhiteSpace(_weChatConfig.ApiUrl) ? "[未配置]" : "[已配置]",
                    _weChatConfig.TimeoutSeconds,
                    _weChatConfig.RetryCount,
                    _weChatConfig.RetryDelayMs
                });
                
                var xml = await GenerateWeChatMessageXmlAsync(request);
                
                _logger.LogInformation($"[{requestId}] {logMessage} - XML生成完成，长度: {xml.Length} 字符");
                
                // HTTP请求发送逻辑
                if (!string.IsNullOrWhiteSpace(_weChatConfig.ApiUrl))
                {
                    _logger.LogInformation($"[{requestId}] 准备发送HTTP请求到: {_weChatConfig.ApiUrl}");
                    
                    var httpContent = new StringContent(xml, Encoding.UTF8, "application/xml");
                    // HttpClient的超时时间已在Program.cs中配置，不需要在运行时修改
                    
                    bool sendSuccess = false;
                    string lastError = string.Empty;
                    
                    for (int i = 0; i < _weChatConfig.RetryCount; i++)
                    {
                        var attemptId = $"{requestId}-{i + 1}";
                        _logger.LogInformation($"[{attemptId}] 开始第{i + 1}次发送尝试");
                        
                        try
                        {
                            var startTime = DateTime.Now;
                            using var httpClient = _httpClientFactory.CreateClient("WeChatClient");
                            var response = await httpClient.PostAsync(_weChatConfig.ApiUrl, httpContent);
                            var duration = DateTime.Now - startTime;
                            
                            _logger.LogInformation($"[{attemptId}] HTTP请求完成，耗时: {duration.TotalMilliseconds:F2}ms, 状态码: {response.StatusCode}");
                            
                            if (response.IsSuccessStatusCode)
                            {
                                var responseContent = await response.Content.ReadAsStringAsync();
                                _logger.LogInformation($"[{attemptId}] 发送成功，响应内容: {responseContent}");
                                sendSuccess = true;
                                break;
                            }
                            else
                            {
                                var errorContent = await response.Content.ReadAsStringAsync();
                                lastError = $"HTTP {response.StatusCode}: {errorContent}";
                                _logger.LogWarning($"[{attemptId}] 发送失败，状态码: {response.StatusCode}, 响应内容: {errorContent}");
                                
                                if (i < _weChatConfig.RetryCount - 1)
                                {
                                    _logger.LogInformation($"[{attemptId}] 将在{_weChatConfig.RetryDelayMs}ms后进行第{i + 2}次重试");
                                    await Task.Delay(_weChatConfig.RetryDelayMs);
                                }
                            }
                        }
                        catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
                        {
                            lastError = $"请求超时: {ex.Message}";
                            _logger.LogWarning($"[{attemptId}] 请求超时，超时时间: {_weChatConfig.TimeoutSeconds}秒");
                            
                            if (i < _weChatConfig.RetryCount - 1)
                            {
                                _logger.LogInformation($"[{attemptId}] 将在{_weChatConfig.RetryDelayMs}ms后进行第{i + 2}次重试");
                                await Task.Delay(_weChatConfig.RetryDelayMs);
                            }
                        }
                        catch (Exception ex)
                        {
                            lastError = $"网络异常: {ex.Message}";
                            _logger.LogWarning(ex, $"[{attemptId}] 发送异常: {ex.Message}");
                            
                            if (i < _weChatConfig.RetryCount - 1)
                            {
                                _logger.LogInformation($"[{attemptId}] 将在{_weChatConfig.RetryDelayMs}ms后进行第{i + 2}次重试");
                                await Task.Delay(_weChatConfig.RetryDelayMs);
                            }
                        }
                    }
                    
                    if (sendSuccess)
                    {
                        _logger.LogInformation($"[{requestId}] {logMessage} - 发送成功");
                    }
                    else
                    {
                        _logger.LogError($"[{requestId}] {logMessage} - 发送失败，已重试{_weChatConfig.RetryCount}次，最后错误: {lastError}");
                    }
                }
                else
                {
                    _logger.LogWarning($"[{requestId}] 微信推送API地址未配置，跳过实际发送");
                }
                
                var result = new WeChatNotificationResult
                {
                    Success = true,
                    Message = "微信通知处理完成",
                    GeneratedXml = xml
                };
                
                _logger.LogInformation($"[{requestId}] {logMessage} - 处理完成，结果: {{@Result}}", new {
                    result.Success,
                    result.Message,
                    XmlLength = result.GeneratedXml?.Length ?? 0
                });
                
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"[{requestId}] {logMessage} - 处理失败: {ex.Message}");
                return new WeChatNotificationResult
                {
                    Success = false,
                    Message = "处理通知失败",
                    ErrorDetails = ex.Message
                };
            }
        }

        /// <summary>
        /// 生成微信推送消息XML
        /// </summary>
        /// <param name="request">微信消息请求</param>
        /// <returns>生成的XML字符串</returns>
        public Task<string> GenerateWeChatMessageXmlAsync(WeChatMessageRequest request)
        {
            var requestId = Guid.NewGuid().ToString("N")[..8]; // 生成8位请求ID用于日志追踪
            
            try
            {
                _logger.LogInformation($"[{requestId}] 开始生成微信推送消息XML");
                
                // 记录原始请求参数
                _logger.LogInformation($"[{requestId}] 原始请求参数: {{@Request}}", new {
                    request.ServiceCode,
                    request.PartnerId,
                    request.TimeStamp,
                    CardNo = string.IsNullOrWhiteSpace(request.CardNo) ? "[空]" : $"{request.CardNo[..Math.Min(8, request.CardNo.Length)]}***", // 脱敏处理
                    request.MsgType,
                    request.MsgContext,
                    request.PersonalFirst,
                    request.PersonalSecond,
                    request.Channel
                });

                // 处理qrCode格式，去掉前缀和后缀
                var processedCardNo = !string.IsNullOrEmpty(request.CardNo) ? ProcessQrCode(request.CardNo) : request.CardNo;

                // 第一步：构建参数字典（排除空值）
                var parameters = new Dictionary<string, string>();
                
                if (!string.IsNullOrEmpty(processedCardNo))
                    parameters.Add("cardNo", processedCardNo);
                if (!string.IsNullOrEmpty(request.Channel))
                    parameters.Add("channel", request.Channel);
                if (!string.IsNullOrEmpty(request.MsgContext))
                    parameters.Add("msgContext", request.MsgContext);
                if (!string.IsNullOrEmpty(request.MsgType))
                    parameters.Add("msgType", request.MsgType);
                if (!string.IsNullOrEmpty(request.PartnerId))
                    parameters.Add("partnerId", request.PartnerId);
                if (!string.IsNullOrEmpty(request.PersonalFirst))
                    parameters.Add("personalFirst", request.PersonalFirst);
                if (!string.IsNullOrEmpty(request.PersonalSecond))
                    parameters.Add("personalSecond", request.PersonalSecond);
                if (!string.IsNullOrEmpty(request.ServiceCode))
                    parameters.Add("serviceCode", request.ServiceCode);
                if (!string.IsNullOrEmpty(request.TimeStamp))
                    parameters.Add("timeStamp", request.TimeStamp);
                
                _logger.LogInformation($"[{requestId}] 有效参数数量: {parameters.Count}, 参数列表: [{string.Join(", ", parameters.Keys)}]");
                
                // 第二步：按ASCII码排序并拼接
                var sortedParams = parameters.OrderBy(p => p.Key, StringComparer.Ordinal);
                var sortedParamsList = sortedParams.ToList();
                
                _logger.LogInformation($"[{requestId}] ASCII排序后参数顺序: [{string.Join(", ", sortedParamsList.Select(p => p.Key))}]");
                
                var paramString = string.Join("&", sortedParamsList.Select(p => $"{p.Key}={p.Value}"));
                var signString = paramString + "&" + _weChatConfig.PartnerId;
                
                _logger.LogInformation($"[{requestId}] 参数拼接字符串: {paramString}");
                _logger.LogInformation($"[{requestId}] 签名字符串: {signString}");
                
                // 第三步：MD5加密并转大写
                var md5Hash = ComputeMD5Hash(signString);
                
                _logger.LogInformation($"[{requestId}] MD5签名结果: {md5Hash}");
                
                // 第四步：生成最终XML
                var finalXml = new XElement("Request",
                    new XElement("serviceCode", request.ServiceCode),
                    new XElement("partnerId", request.PartnerId),
                    new XElement("timeStamp", request.TimeStamp),
                    new XElement("password", md5Hash),
                    new XElement("cardNo", processedCardNo),
                    new XElement("msgType", request.MsgType),
                    new XElement("msgContext", request.MsgContext),
                    new XElement("personalFirst", request.PersonalFirst),
                    new XElement("personalSecond", request.PersonalSecond),
                    new XElement("channel", request.Channel)
                );
                
                var xmlString = finalXml.ToString();
                _logger.LogInformation($"[{requestId}] 生成的最终XML: {xmlString}");
                _logger.LogInformation($"[{requestId}] 微信推送消息XML生成完成");
                
                return Task.FromResult(xmlString);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"[{requestId}] 生成微信推送XML失败");
                throw;
            }
        }

        /// <summary>
        /// 计算MD5哈希值
        /// </summary>
        private string ComputeMD5Hash(string input)
        {
            using (var md5 = MD5.Create())
            {
                var inputBytes = Encoding.UTF8.GetBytes(input);
                var hashBytes = md5.ComputeHash(inputBytes);
                return Convert.ToHexString(hashBytes).ToUpper();
            }
        }

        /// <summary>
        /// 处理qrCode格式
        /// 对于形如 "772:8fc46570-9168-11e9-87f8-38adbeda02ff:1" 的格式，提取中间的UUID部分
        /// 对于形如 ";81293687|82665666?" 的格式，返回第一个数字部分 "81293687"
        /// 对于形如 ";9000348143=99015017511?" 的格式，返回第一个数字部分 "9000348143"
        /// </summary>
        /// <param name="qrCode">原始qrCode</param>
        /// <returns>处理后的qrCode</returns>
        private string ProcessQrCode(string qrCode)
        {
            if (string.IsNullOrEmpty(qrCode))
            {
                return qrCode;
            }

            // 检查是否为形如 "772:8fc46570-9168-11e9-87f8-38adbeda02ff:1" 的格式
            // 这种格式的特征是：数字:UUID:数字
            if (qrCode.Contains(':'))
            {
                var parts = qrCode.Split(':');
                if (parts.Length == 3)
                {
                    // 检查第一部分是否为数字，第二部分是否为UUID格式，第三部分是否为数字
                    if (int.TryParse(parts[0], out _) && 
                        IsValidUuid(parts[1]) && 
                        int.TryParse(parts[2], out _))
                    {
                        // 提取中间的UUID部分
                        var result = parts[1];
                        _logger.LogInformation($"qrCode格式处理: 原始='{qrCode}' -> 处理后='{result}' (UUID提取)");
                        return result;
                    }
                }
            }
            
            // 检查是否为形如 ";81293687|82665666?" 或 ";9000348143=99015017511?" 的格式
            // 去掉开头的分号和结尾的问号
            var trimmed = qrCode.Trim(';', '?');
            
            // 检查是否包含 | 或 = 分隔符
            if (trimmed.Contains('|') || trimmed.Contains('='))
            {
                // 使用 | 或 = 作为分隔符，取第一部分
                var separators = new char[] { '|', '=' };
                var parts = trimmed.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length >= 1 && !string.IsNullOrWhiteSpace(parts[0]))
                {
                    var result = parts[0].Trim();
                    _logger.LogInformation($"qrCode格式处理: 原始='{qrCode}' -> 处理后='{result}' (分隔符提取)");
                    return result;
                }
            }
            
            // 对于其他格式，直接返回原值
            _logger.LogInformation($"qrCode格式处理: 原始='{qrCode}' -> 保持原值 (其他格式)");
            return qrCode;
        }

        /// <summary>
        /// 检查字符串是否为有效的UUID格式
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>是否为有效UUID</returns>
        private bool IsValidUuid(string input)
        {
            return Guid.TryParse(input, out _);
        }
    }
}